import pytest
import sqlite3
from pathlib import Path
from unittest.mock import Mock
from datetime import date
from exceptions import NoDataException, DuplicateKeyException


# 被测服务类
class ReportService:
    def generate_report(self, report_type, start_date, end_date, format):
        filename = f"{report_type}_{start_date}_{end_date}.{format.lower()}"
        return Path(filename)


class StatisticsService:
    def calculate_total_sales(self, start_date, end_date):
        # 实际实现应查询数据库
        if start_date > date(2024, 1, 1):
            raise NoDataException()
        return 150000.0


class UserService:
    def __init__(self, conn):
        self.conn = conn

    def create_user(self, username):
        try:
            self.conn.execute("INSERT INTO users (username) VALUES (?)", (username,))
            self.conn.commit()
        except sqlite3.IntegrityError:
            self.conn.rollback()
            raise DuplicateKeyException()


# 测试实现
@pytest.fixture(scope="module")
def test_db():
    """内存数据库测试夹具"""
    conn = sqlite3.connect(":memory:")
    yield conn
    conn.close()


@pytest.fixture
def reset_db(test_db):
    """重置测试数据夹具"""
    test_db.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT UNIQUE)")
    test_db.execute("DELETE FROM users")
    test_db.execute("INSERT INTO users (username) VALUES ('admin')")
    test_db.commit()


class TestReportGeneration:
    @pytest.fixture
    def report_service(self):
        return ReportService()

    def test_pdf_report_generation(self, report_service, tmp_path):
        # 测试文件生成
        os.chdir(tmp_path)
        report = report_service.generate_report("sales", "20240101", "20241231", "PDF")

        assert report.exists(), "PDF报表文件应存在"
        assert report.name == "sales_20240101_20241231.pdf", "文件名格式不正确"


class TestReportStatistics:
    @pytest.fixture
    def stats_service(self):
        return StatisticsService()

    def test_sales_amount_calculation(self, stats_service):
        result = stats_service.calculate_total_sales("2024-01-01", "2024-12-31")
        assert abs(result - 150000.0) < 0.01, "销售额统计不准确"

    def test_empty_data_statistics(self, stats_service):
        with pytest.raises(NoDataException):
            stats_service.calculate_total_sales("2099-01-01", "2099-12-31")


class TestDatabaseUpdates:
    def test_transaction_rollback(self, test_db, reset_db):
        service = UserService(test_db)

        with pytest.raises(DuplicateKeyException):
            service.create_user("admin")

        cur = test_db.execute("SELECT COUNT(*) FROM users")
        assert cur.fetchone()[0] == 1, "事务回滚后用户数应不变"

    def test_batch_update(self, test_db):
        test_db.execute("CREATE TABLE products (id INTEGER PRIMARY KEY, price REAL)")
        test_db.executemany("INSERT INTO products VALUES (?, ?)", [(i, 5.0) for i in range(100)])

        test_db.execute("UPDATE products SET price = ?", (10.0,))
        test_db.commit()

        cur = test_db.execute("SELECT price FROM products WHERE id = 1")
        assert cur.fetchone()[0] == 10.0, "价格更新失败"


